package com.sulent.frame.file.impl;

import com.jcraft.jsch.*;
import com.sulent.frame.file.FileServer;
import com.sulent.frame.file.dto.FileVo;
import com.sulent.frame.support.exception.BaseException;
import com.sulent.frame.support.utils.FileUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

/**
 * @ClassName SFTPFileServer
 * @Description: 基于JSch实现SFTP文件处理
 * @Author Submerge.
 * @Since 2024/1/24 14:36
 * @Version 1.0
 */
@Data
public class SftpFileServer implements FileServer {

    private String username;
    private String password;
    private String host;
    private int port;
    private int timeout;

    public SftpFileServer(String host,int port,String username,String password,int timeout){
        this.host=host;
        this.port = port;
        this.username=username;
        this.password=password;
        this.timeout=timeout;
    }


    @Override
    public void uploadFile(File file, String targetPath) {

    }

    @Override
    public File downloadFile(String sourceFilePath, String targetPath) {
        File file = new File(targetPath);
        OutputStream dst = null;
        if (!file.exists()){
            boolean mkdirs = file.mkdirs();
        }
        ChannelSftp channel = null;
        try {
            String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/")+1);
            channel = getChannel();
            file = new File(file,fileName);
            dst = new FileOutputStream(file);
            channel.get(sourceFilePath,dst);//获取远程服务器文件
        } catch (JSchException | SftpException | IOException e) {
            e.printStackTrace();
            throw new BaseException("SFTP下载文件异常："+e.getMessage());
        } finally {
            disconnect(channel);
            if (dst!=null){
                try {
                    dst.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return file;
    }

    @Override
    public List<FileVo> listFiles(String targetPath) {
        try {
            ChannelSftp channel = getChannel();
            Vector<ChannelSftp.LsEntry> files = null;
            if (StringUtils.isNotBlank(targetPath)){
                files = channel.ls(targetPath);
            }
            List<FileVo> fileVos = new ArrayList<>();
            if (files==null || files.size()<=0){
                return fileVos;
            }
            for (ChannelSftp.LsEntry file : files) {
                String filename = file.getFilename();
                if (".".equals(filename) || "..".equals(filename)) {
                    continue;
                }
                FileVo fileVo = new FileVo();
                fileVo.setName(filename);
                fileVo.setSize(file.getAttrs().getSize());
                fileVo.setType(file.getAttrs().isDir()?"DIRECTORY":"FILE");
                fileVos.add(fileVo);
            }
            disconnect(channel);
            return fileVos;
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     *
     * @return
     * @throws JSchException
     */
    private ChannelSftp getChannel() throws JSchException {
        Channel channel = null;
        //创建JSch对象
        JSch jsch = new JSch();
        //根据用户名，主机ip，端口获取一个Session对象
        Session session = jsch.getSession(username, host, port);
        session.setPassword(password);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config); // 为Session对象设置properties
        session.setTimeout(timeout); // 设置timeout时间
        try {
            session.connect(); // 通过Session建立链接
            channel = session.openChannel("sftp");// 打开SFTP通道
            channel.connect(); // 建立SFTP通道的连接
        } catch (Exception e) {
            if (session.isConnected())
                session.disconnect();
            if (channel != null && channel.isConnected())
                channel.disconnect();
            e.printStackTrace();
            throw new RuntimeException("连接SFTP服务器失败,请检查主机[" + host + "],端口[" + port + "],用户名[" + username + "],端口[" + port + "]是否正确,以上信息正确的情况下请检查网络连接是否正常或者请求被防火墙拒绝.");
        }
        return (ChannelSftp) channel;
    }

    /**
     * 断开连接
     */

    private void disconnect(ChannelSftp channelSftp) {
        if (channelSftp!=null){
            try {
                Session session = channelSftp.getSession();
                session.disconnect();
                channelSftp.disconnect();
            } catch (JSchException e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public void close() throws Exception {
        System.out.println("sftp file sever close");
    }
}
